﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Spinning.Spinning.Unitity;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Phone.Info;
using System.Windows.Threading;
using System.Collections.ObjectModel;
using com.google.zxing.qrcode;
using Microsoft.Devices;
using com.google.zxing.common;
using com.google.zxing;
using System.Net;
using System.Windows.Media;

namespace Spinning.Spinning.Entity.Scenes
{
    class ConnectScene : BaseScene
    {
        TextEntity te;
        QRSprite QR;
        Sprite itemTitleSprite, barSprite, qrTextSprite, scanSprite;
        ButtonSprite createQRSprite, scanQRSprite,homeSprite,backSprite;
        List<Sprite> _rectangleSpriteList = new List<Sprite>();
        bool isHost;
        int QRsize = 300;

        //Reader
        private DispatcherTimer _timer;
        private ObservableCollection<string> _matches;

        private PhotoCameraLuminanceSource _luminance;
        private QRCodeReader _reader;
        private static PhotoCamera _photoCamera;
        private static VideoBrush _previewVideo;
        //End of Reader
        
        //UDP
        private UdpAnySourceMulticastChannel Channel { get; set; }
        //

        public ConnectScene()
            : base()
        {
            Size = new Vector2(1);
        }

        public override void OnLoad()
        {
            base.OnLoad();

            te = new TextEntity();
            ResourceManager.ContentRoot = "";
            te.fontString = "TestFont";
            te.OnLoad();
            te.Origin = new Vector2(0.5f);
            te.Position = new Vector2(200, 50);
            te.Color = Microsoft.Xna.Framework.Color.Blue;
            te.Alpha = 0;
            te.ZIndex = Constants.debugText;
            Attach(te);

            Sprite backGroundSprite = new Sprite();
            backGroundSprite.textureName = "bg";
            backGroundSprite.ZIndex = Constants.background;
            backGroundSprite.OnLoad();
            this.Attach(backGroundSprite);

            SetFrontView();
            SetControlButton();
            SetScanMode();
            SetCreateMode();

            SetFrontViewVisable(true);
            SetControlVisable(false);
            SetScanModeVisable(false);
            SetCreateModeVisable(false);

            ReaderInit();

            //UDP
            this.Channel = new UdpAnySourceMulticastChannel(IPAddress.Parse("224.0.1.100"), 3000);
            this.Channel.AfterOpen += new EventHandler(Channel_AfterOpen);
            this.Channel.BeforeClose += new EventHandler(Channel_BeforeClose);
            this.Channel.PacketReceived += new EventHandler<UdpPacketReceivedEventArgs>(Channel_PacketReceived);

            this.Channel.Open();
            //
        }

        private void SetCreateMode()
        {
            // QRcode
            QR = new QRSprite("Spinning Connect!," + Game1.GetDeviceUniqueID() + ",", new Point(QRsize, QRsize));
            QR.Position = new Vector2(240 - QRsize / 2, 300 - QRsize / 2);
            QR.ZIndex = Constants.ui;
            QR.Alpha = 1;
            this.Attach(QR);
            //
        }

        private void SetCreateModeVisable(bool flag)
        {
            QR.Visable = flag;
        }

        private void SetControlButton()
        {
            homeSprite = new ButtonSprite();
            homeSprite.textureName = "p4/home";
            homeSprite.ZIndex = Constants.ui;
            homeSprite.Origin = new Vector2(0.5f);
            homeSprite.Position = new Vector2(315, 700);
            homeSprite.OnLoad();
            homeSprite.Visable = false;
            homeSprite.OnTouchEvent += OnHomeTouch;
            TouchManager.RegisteTouchArea(homeSprite);
            this.Attach(homeSprite);

            backSprite = new ButtonSprite();
            backSprite.textureName = "p2/back";
            backSprite.ZIndex = Constants.ui;
            backSprite.Origin = new Vector2(0.5f);
            backSprite.Position = new Vector2(395, 700);
            backSprite.OnLoad();
            backSprite.Visable = false;
            backSprite.OnTouchEvent += OnBackTouch;
            TouchManager.RegisteTouchArea(backSprite);
            this.Attach(backSprite);

            // qrTextSprite
            qrTextSprite = new Sprite();
            qrTextSprite.textureName = "pvp/txt_QR code";
            qrTextSprite.ZIndex = Constants.ui;
            qrTextSprite.Origin = new Vector2(0.5f);
            qrTextSprite.Position = new Vector2(240, 530);
            qrTextSprite.OnLoad();
            qrTextSprite.Alpha = 1;
            this.Attach(qrTextSprite);
            //
        }

        private void SetControlVisable(bool flag)
        {
            homeSprite.Visable = flag;
            backSprite.Visable = flag;
            qrTextSprite.Visable = flag;
            if (flag) 
            {
                homeSprite.OnTouchEvent += OnHomeTouch;
                backSprite.OnTouchEvent += OnBackTouch;
            }
            else 
            {
                homeSprite.OnTouchEvent -= OnHomeTouch;
                backSprite.OnTouchEvent -= OnBackTouch;
            }
        }

        private void SetScanMode()
        {
            Vector2 rectangleCenter = new Vector2(240, 300);
            for (int i = 0; i < 4; i++)
            {
                Sprite r = new Sprite();
                r.textureName = "pvp/bracket";
                r.ZIndex = Constants.ui;
                r.Origin = new Vector2(0.5f);
                r.Position = new Vector2(rectangleCenter.X - QRsize / 2 + (i % 2) * QRsize, rectangleCenter.Y - QRsize / 2 + ((int)i / 2) * QRsize);
                if (i >= 2) r.Rotation = (float)(Math.PI / 2) * (-i + 1);
                else r.Rotation = (float)(Math.PI / 2) * i;
                r.OnLoad();
                r.Alpha = 1;
                this.Attach(r);
                _rectangleSpriteList.Add(r);
            }

            scanSprite = new Sprite();
            scanSprite.textureName = "pvp/txt_scan";
            scanSprite.ZIndex = Constants.ui;
            scanSprite.Origin = new Vector2(0.5f);
            scanSprite.Position = rectangleCenter;
            scanSprite.OnLoad();
            scanSprite.Alpha = 1;
            this.Attach(scanSprite);

            
        }

        private void SetScanModeVisable(bool flag)
        {
            for (int i = 0; i < _rectangleSpriteList.Count; i++)
            {
                _rectangleSpriteList[i].Visable = flag;
            }
            scanSprite.Visable = flag;
        }

        private void SetFrontView()
        {
            itemTitleSprite = new Sprite();
            itemTitleSprite.textureName = "pvp/scroll_txt_connecting";
            itemTitleSprite.ZIndex = Constants.ui;
            itemTitleSprite.Origin = new Vector2(0.5f);
            itemTitleSprite.OnLoad();
            itemTitleSprite.Position = new Vector2(240, 125);
            this.Attach(itemTitleSprite);

            barSprite = new Sprite();
            barSprite.textureName = "pvp/scroll_b";
            barSprite.ZIndex = Constants.uibackground;
            barSprite.Origin = new Vector2(0.5f);
            barSprite.OnLoad();
            barSprite.Position = new Vector2(240, 125);
            this.Attach(barSprite);

            createQRSprite = new ButtonSprite();
            createQRSprite.textureName = "pvp/btn_create";
            createQRSprite.ZIndex = Constants.ui;
            createQRSprite.Origin = new Vector2(0.5f);
            createQRSprite.Position = new Vector2(240, 340);
            createQRSprite.OnLoad();
            
            TouchManager.RegisteTouchArea(createQRSprite);
            this.Attach(createQRSprite);

            scanQRSprite = new ButtonSprite();
            scanQRSprite.textureName = "pvp/btn_scan";
            scanQRSprite.ZIndex = Constants.ui;
            scanQRSprite.Origin = new Vector2(0.5f);
            scanQRSprite.Position = new Vector2(240, 520);
            scanQRSprite.OnLoad();
            
            TouchManager.RegisteTouchArea(scanQRSprite);
            this.Attach(scanQRSprite);
        }

        void SetFrontViewVisable(bool flag) 
        {
            itemTitleSprite.Visable = flag;
            barSprite.Visable = flag;
            createQRSprite.Visable = flag;
            scanQRSprite.Visable = flag;
            if (flag)
            {
                scanQRSprite.OnTouchEvent += OnScanTouch;
                createQRSprite.OnTouchEvent += OnCreateTouch;
            }
            else 
            {
                scanQRSprite.OnTouchEvent -= OnScanTouch;
                createQRSprite.OnTouchEvent -= OnCreateTouch;
            }
        }

        void ReaderInit()
        {
            _matches = new ObservableCollection<string>();

            _timer = new DispatcherTimer();
            _timer.Interval = TimeSpan.FromMilliseconds(250);
            _timer.Tick += (o, arg) => ScanPreviewBuffer();

            if (_photoCamera == null)
            {
                _photoCamera = new PhotoCamera(CameraType.Primary);
                _photoCamera.Initialized += OnPhotoCameraInitialized;
            }

            if (_previewVideo == null)
            {
                _previewVideo = new System.Windows.Media.VideoBrush();
                _previewVideo.SetSource(_photoCamera);
            }

            _timer.Tick += (o, arg) => cameraFocus();
            //CameraButtons.ShutterKeyHalfPressed += (o, arg) => _photoCamera.Focus();
        }

        void cameraFocus() 
        {
            if (_photoCamera != null) 
            {
                _photoCamera.Focus();
            }
        }

        void OnCreateTouch(BaseEntity entity, TouchLocation touchLocation)
        {
            SetFrontViewVisable(false);
            SetCreateModeVisable(true);
            SetControlVisable(true);

            isHost = false; //我是client
            Game1.clientId = Game1.GetDeviceUniqueID();
            //te.Value = "CLIENT";
        }

        void OnScanTouch(BaseEntity entity, TouchLocation touchLocation)
        {
            SetFrontViewVisable(false);
            SetScanModeVisable(true);
            SetControlVisable(true);

            isHost = true;
            _timer.Start();
            //te.Value = "HOST";
        }

        void OnHomeTouch(BaseEntity entity, TouchLocation touchLocation)
        {
            _timer.Stop();
            stopCamera();
            
            Game1.stageManager.GoToScene("role");
        }

        void OnBackTouch(BaseEntity entity, TouchLocation touchLocation)
        {
            SetFrontViewVisable(true);
            SetScanModeVisable(false);
            SetCreateModeVisable(false);
            SetControlVisable(false);

            _timer.Stop();
            Game1.clientId = ""; 
        }

        private void OnPhotoCameraInitialized(object sender, CameraOperationCompletedEventArgs e)
        {
            int width = Convert.ToInt32(_photoCamera.PreviewResolution.Width);
            int height = Convert.ToInt32(_photoCamera.PreviewResolution.Height);

            _luminance = new PhotoCameraLuminanceSource(width, height);
            _reader = new QRCodeReader();
        }

        private void ScanPreviewBuffer()
        {
            try
            {
                _photoCamera.GetPreviewBufferY(_luminance.PreviewBufferY);
                var binarizer = new HybridBinarizer(_luminance);
                var binBitmap = new BinaryBitmap(binarizer);
                var result = _reader.decode(binBitmap);
                _previewVideo.Dispatcher.BeginInvoke(() =>
                    DisplayResult(result.Text));
            }
            catch
            {
            }
        }

        private void DisplayResult(string text)
        {
            _timer.Stop();
            if (!_matches.Contains(text))
                _matches.Add(text);
            te.Value = text;

            string[] temp;

            temp = text.Split(',');

            if (temp[0] == "Spinning Connect!")  //你是Host
            {
                onSuccessReadEnemyInfo(temp[1]);
                QRSprite hostQR = new QRSprite("Spinning Connect!," + temp[1] + ",", new Point(QRsize, QRsize));
                hostQR.Position = new Vector2(240 - QRsize / 2, 300 - QRsize / 2);
                hostQR.ZIndex = Constants.ui;
                hostQR.Alpha = 1;
                this.Attach(hostQR);
                //GoToHostScene();
            }
        }

        void onSuccessReadEnemyInfo(String clientId)
        {
            //te.Value = clientId;
            Game1.clientId = clientId;

            this.Channel.Send("hostId:{0},clientId:{1},isHost:{2},", Game1.hostId, clientId, isHost);
            
            stopCamera();
            //GoToScene();
        }

        void stopCamera()
        {
            //dispose PhotoCamera
            //if (_photoCamera != null)
            //    _photoCamera.Dispose();
            //_photoCamera = null;
        }

        //void GoToClientScene()
        //{
        //    Game1.stageManager.GoToScene("client");
        //}

        //void GoToHostScene()
        //{
        //    Game1.stageManager.GoToScene("host");
        //}

        void GoToBattle() 
        {
            Game1.stageManager.IsHost = isHost;
            if (isHost) Game1.stageManager.GoToScene("lifeHost");
            else Game1.stageManager.GoToScene("lifeClient");
        }

        void Channel_PacketReceived(object sender, UdpPacketReceivedEventArgs e)
        {
            //if(e.Message.Length!=0)
            //te.Value = e.Message;

            string[] temp;
            string[] temp1;

            temp = e.Message.Split(',');

            NoKeyFoundDictionary dataDictionary = new NoKeyFoundDictionary();

            bool partyFlag = false;

            for (int i = 0; i < temp.Length; i++)
            {
                temp1 = temp[i].Split(':');
                if(temp1.Length>=2)
                dataDictionary.Add(temp1[0], temp1[1]);
            }

            

            if (dataDictionary.Get("hostId") == Game1.hostId && dataDictionary.Get("clientId") == Game1.clientId)
            {
                partyFlag = true;
                if (dataDictionary.Get("clientAns") == "true" && dataDictionary.Get("isHost")=="False")
                {
                    if (isHost)
                    {
                        startFlag = true;  //倒數計時的flag
                    }
                }
            }
            else if (dataDictionary.Get("clientId") == Game1.clientId && dataDictionary.Get("hostId")!="noKey")   // client 知道host是誰
            {
                Game1.hostId = dataDictionary.Get("hostId");
                partyFlag = true;
                this.Channel.Send("clientAns:true,hostId:{0},clientId:{1},isHost:{2},", Game1.hostId, Game1.clientId, isHost);
                startFlag = true; //倒數計時的flag
            }
            else
            {
                partyFlag = false;
            }
        }

        void Channel_BeforeClose(object sender, EventArgs e)
        {
            this.Channel.Send("END,{0}, leaves the UDP Multicast chat,", Game1.hostId);
        }

        void Channel_AfterOpen(object sender, EventArgs e)
        {
            this.Channel.Send("BEGIN,{0}, enters the UDP Multicast chat,", Game1.hostId);
        }

        int _gameTime, scanflag, startCounter,showTimer = 2;
        bool startFlag = false;
        protected override void UpdateSelf(GameTime gameTime)
        {
            base.UpdateSelf(gameTime);
            int delta = gameTime.ElapsedGameTime.Milliseconds;
            _gameTime += delta;
            if (_gameTime / 1000 >= 1)
            {
                scanflag = -scanflag + 1;
                _gameTime = _gameTime % 1000;
            }
            if (scanflag == 0) scanSprite.Alpha = ((float)(_gameTime % 1000) / 1000) * 0.7f + 0.3f;
            else scanSprite.Alpha = (1f - (float)(_gameTime % 1000) / 1000) * 0.7f + 0.3f;

            if (startFlag) 
            {
                startCounter += delta;
                if (startCounter / 1000 >= 1)
                {
                    startCounter = startCounter % 1000;
                    showTimer--;
                    if (showTimer == 0) 
                    {
                        GoToBattle();
                    }
                }
            }
            te.Value = "" + scanQRSprite.Visable;
        }

        public override BaseScene Clone()
        {
            BaseScene scene = new ConnectScene();
            scene.Size = new Vector2(Constants.Window_Width, Constants.Window_Height);
            scene.OnLoad();
            scene.SortChildren();
            return scene;
        }
    }
}
